/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.fjsei.yewu.unit;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
import graphql.GraphQLContext;
import graphql.com.google.common.collect.Lists;
import graphql.relay.Connection;
import graphql.relay.SimpleListConnection;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import md.cm.base.*;
import md.cm.unit.*;
import md.system.QUser;
import md.system.User;
import org.fjsei.yewu.filter.NodeName;
import org.fjsei.yewu.jpa.QBeanMy;
import org.fjsei.yewu.resolver.Comngrql;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.query.FluentQuery;
import org.springframework.data.web.ProjectedPayload;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.BatchMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.graphql.execution.BatchLoaderRegistry;
import org.springframework.stereotype.Controller;
import reactor.core.publisher.Mono;

import java.util.*;

/**默认Unit模型的属性； graphQL接口;
 * 底下批处理方案还不是一种的。 注释掉的也是1个方案。
 * */
@Controller
public class UnitController extends Comngrql {
	private final Units units;
	private final Companies companies;
	private final Persons persons;

//	public UnitController(Units units, Companies companies) {
//		this.units = units;
//		this.companies = companies;
//	}

	/** registry参数：IDEA报红却能运行成功，实际运行注入DefaultBatchLoaderRegistry;
     *  消除报红，测试平台Units没有报红 https://blog.csdn.net/zy103118/article/details/84523452
	 * 添加了 @ComponentScan({"md","org.fjsei.yewu"}) 以后: Units报红消除了。
	 * */
	public UnitController(BatchLoaderRegistry registry, Units units, Companies companies, Persons persons) {
		this.units = units;
		this.companies = companies;
//		//启动时刻仅注册，内部函数真正运行是在底下CompletableFuture<Company> company(Unit unit, DataLoader<UUID, Company> loader)收集到所有ID以后的！
//		registry.forTypePair(UUID.class, Company.class).registerMappedBatchLoader((companyIds, env) -> {
//		//	return Mono.just(mapkv); //类型来源registerMappedBatchLoader(BiFunction<Set<K>, BatchLoaderEnvironment, Mono<Map<K, V>>> loader);
//			return Mono.defer(() ->{
//				List<Company>  companyList=companies.findAllById(companyIds);
//				Map<UUID, Company>  mapkv = companyList.stream().collect(Collectors.toMap(Company::getId, Function.identity(), (key1, key2) -> key2));
//				return Mono.just(mapkv);
//			} );
//		});
		this.persons = persons;
	}
	/**这个会在父辈graphql的接口执行中的内省阶段才会执行：收集批量执行的ID，然后才是运行上面registerMappedBatchLoader注册的内部函数。
	 * */
//	@SchemaMapping
//	public CompletableFuture<Company> company(Unit unit, DataLoader<UUID, Company> loader) {
//		if(null!=unit.getCompany())
//			return loader.load(unit.getCompany().getId());	   //一对多的关联 loadMany()? 需要从相反方向查找IDs：性能有问题啊？感觉不适合这种机制;
//		else
//			return null;
//	}


	/**简化模式：感觉更加难搞？ 函数参数company(List<Unit> units)类型Unit不能改，否则无效。
	 * 因为采用自定义方案findBy(piExp, predicate, (query)-> {})，所以后面内省连带的也要特殊处理了，类型cast报错。
	 *若改为Mono<Map<UnitPi, Company>> company(List<UnitPi> units){ }是无法捕捉到的：就和没有注册@Batch没有该函数一样的。
	 *进入到这里名义上是List<Unit>类型 units：可是实质可能是List<UnitPi>，所以直接读Unit运行报错,需要特别处理,无法编译。
	 * UnitPi是含有了getCompany()的最小化接口类。ObjectPi是含getId()基础接口,  <PI> 才是真实投影类。
	 **/
    @BatchMapping
    public  Mono<Map<UnitPi, Company>>  company(List<Unit> units) {
		return Mono.defer(() ->{
			//一对一情况下可以的： #但是多对一：假设若多个unit 对应 同一个的company? 按以下处理做法的就行不通： companyId2Unit: Map<companyId=>List<Unit>>;
			List<UUID>  companyIds = new ArrayList<>();
			HashMap<UUID, UnitPi>  companyId2Unit= new HashMap<>();
			for(UnitPi unit: units){
				CompanyPi company=unit.getCompany();		//UnitPi是含有了getCompany()的最小化接口类
				if(null!=company) {
					companyIds.add(company.getId());
					companyId2Unit.put(company.getId(), unit);
				}
			}
			List<Company>  companyList= companies.findAllById(companyIds);	 //批量执行SQL;
			HashMap<UnitPi, Company>  mapkv= new HashMap<>();
			for(int i=0; i<companyList.size(); i++) {
				Company company=companyList.get(i);
				mapkv.put(companyId2Unit.get(company.getId()), company);
			}
			for(int i=0; i<companyIds.size(); i++) {		 //？ 需要对companyId上一步SQL查询: 没实际Company对象的设置吗 ?
				UnitPi unit=companyId2Unit.get(companyIds.get(i));
				if(!mapkv.containsKey(unit))	mapkv.put(unit, null);
			}
			return Mono.just(mapkv);
			} );
    }
	/**接口getAllEqpEsFilter获取的EqpEs若遇到Unit类型的属性useu.Person的必须；EqpEs里面useu.Person.id没有存储导致这里实际ID都是空所以关联内省person也是null了。
	 **/
	@BatchMapping
	public  Mono<Map<UnitPi, Person>>  person(List<Unit> units) {
		return Mono.defer(() ->{
			//一对一情况下可以的： #但是多对一：假设若多个unit 对应 同一个的company? 按以下处理做法的就行不通： fieldId2Model: Map<companyId=>List<Unit>>;
			List<UUID>  fieldIds = new ArrayList<>();
			HashMap<UUID, UnitPi>  fieldId2Model= new HashMap<>();
			for(UnitPi unit: units){
				NodeName fieldObj= (NodeName) unit.getPerson();		//UnitPi是含有了getCompany()的最小化接口类
				if(null!=fieldObj) {
					fieldIds.add((UUID) fieldObj.getId());
					fieldId2Model.put((UUID) fieldObj.getId(), unit);
				}
			}
			List<Person>  fieldObjList= persons.findAllById(fieldIds);	 //批量执行SQL;
			HashMap<UnitPi, Person>  mapkv= new HashMap<>();
			for(int i=0; i<fieldObjList.size(); i++) {
				Person field=fieldObjList.get(i);
				mapkv.put(fieldId2Model.get(field.getId()), field);
			}
			for(int i=0; i<fieldIds.size(); i++) {		 //？ 需要对companyId上一步SQL查询: 没实际Company对象的设置吗 ?
				UnitPi unit=fieldId2Model.get(fieldIds.get(i));
				if(!mapkv.containsKey(unit))	mapkv.put(unit, null);
			}
			return Mono.just(mapkv);
		} );
	}
	/**默认不需要自己写代码没用findBy(接口投影自制定,)的情况的：用这个就行，@BatchMapping的
	 * */
	@BatchMapping
	public  Mono<Map<Unit, Company>> company正常(List<Unit> units) {
		return Mono.defer(() ->{
			//一对一情况下可以的： #但是多对一：假设若多个unit 对应 同一个的company? 按以下处理做法的就行不通： companyId2Unit: Map<companyId=>List<Unit>>;
			List<UUID>  companyIds = new ArrayList<>();
			HashMap<UUID, Unit>  companyId2Unit= new HashMap<>();
			units.forEach(unit -> {
						if(null!=unit.getCompany())	{
							companyIds.add(unit.getCompany().getId());
							companyId2Unit.put(unit.getCompany().getId(), unit);
						}
					}
			);
			List<Company>  companyList= companies.findAllById(companyIds);	 //批量执行SQL;
			HashMap<Unit, Company>  mapkv= new HashMap<>();
			for(int i=0; i<companyList.size(); i++) {
				Company company=companyList.get(i);
				mapkv.put(companyId2Unit.get(company.getId()), company);
			}
			for(int i=0; i<companyIds.size(); i++) {		 //？ 需要对companyId上一步SQL查询: 没实际Company对象的设置吗 ?
				Unit unit=companyId2Unit.get(companyIds.get(i));
				if(!mapkv.containsKey(unit))	mapkv.put(unit, null);
			}
			return Mono.just(mapkv);
		} );
	}


/*	@QueryMapping
	public Project project2(@Argument String slug) {
		return client.fetchProject(slug);
	}*/

	//@SchemaMapping
	// Page<Book> books(@QuerydslPredicate(root = Book.class) Predicate predicate)
	//				Pageable pageable , @Argument Map<String, Object> parameters
	/* (@Arguments("bookInput")  BookInputProjection bookInput)

{
    books(name:"做法是",id:"fff") {
        id,name,url  snapshotsEnabled
    }
}
DataLoader<String, Book> loader;	 @ContextValue Predicate predicate,
	* */
	@QueryMapping
	public List<Unit> unitRepository_fail(GraphQLContext ctx, DataFetchingEnvironment dfe) throws Exception {

		Pageable pageable= PageRequest.of(0, 2);
		Sort sort=null;
	  	//Predicate predicate=null;
	//	 predicate = QBook.book.id.equalsIgnoreCase(bookInput.getId())
	//			.and(QBook.book.name.startsWithIgnoreCase(bookInput.getName()));
		//books.findAll(predicate, pageable);
		DataFetcher<Iterable<Unit>> dataFetcher =
			null;//	QuerydslDataFetcher.builder(unitRepository).many();		//可加.sortBy(sort)
		List<Unit>  units= (List<Unit>) dataFetcher.get(dfe);
		return units;
		//return books.findAll(pageable);
	}
	//@QuerydslPredicate只能用在MVC rest URL参数上面。报错Cannot invoke "Object.getClass()" because "source" is null
	/*
	Fluent Query API support for Querydsl支持： https://docs.spring.io/spring-data/commons/docs/current/reference/html/#core.extensions.querydsl
		@SuppressWarnings("unchecked")
		public Iterable<R> get(DataFetchingEnvironment env) {
			return this.executor.findBy(buildPredicate(env), query -> {
				FetchableFluentQuery<R> queryToUse = (FetchableFluentQuery<R>) query;

				if (this.sort.isSorted()){
					queryToUse = queryToUse.sortBy(this.sort);
				}

				if (requiresProjection(this.resultType)){
					queryToUse = queryToUse.as(this.resultType);
				}
				else {
					queryToUse = queryToUse.project(buildPropertyPaths(env.getSelectionSet(), this.resultType));
				}

				return queryToUse.all();
			});
		}
	* */
	@QueryMapping
	public Slice<UnitPi> unitRepository字符串(@Argument UnitInputProjection uinput) {
		Pageable pageable= PageRequest.of(0, 11);
		Predicate predicate=null;
		predicate = QUnit.unit.cancel.eq(uinput.getCancel())
				.and(QUnit.unit.indCod.startsWithIgnoreCase(uinput.getIndCod()));
		//Slice<UnitPi> slice= unitRepository.readAllBy(pageable, UnitPi.class); //unitRepository.<UnitPi,Slice<UnitPi>>findBy();
		List<String> properties= Lists.newArrayList("id","cancel","area","company.id","company.name","person.id","person.name");
		Slice<UnitPi> slice= units.findBy(properties, predicate, (query)-> {
			FluentQuery.FetchableFluentQuery<UnitPi> queryUse = query.as(UnitPi.class);    //返回类型要求; <R> FetchableFluentQuery<R> as(Class<R> resultType); UnitPi.class
			//queryUse= queryUse.project("id","indCod","cancel"); //没影响到select！但是影响返回可用字段，所以关联字段1+N可能会被抑制掉。对父类findBy有好处，自定做findBy就没啥用了。
			//queryUse= queryUse.project("id","indCod","cancel"); //有关联对象字段的报错join！
			return  queryUse.page(pageable);
		});
		return slice;
	}
	//@Transactional
	@QueryMapping
	public <T> Slice<UnitPi> unitRepository简易接口(@Argument UnitInputProjection uinput) {
		Pageable pageable= PageRequest.of(0, 11);
		Predicate predicate=null;
		predicate = QUnit.unit.cancel.eq(uinput.getCancel())
				.and(QUnit.unit.indCod.startsWithIgnoreCase(uinput.getIndCod()));
		Slice<UnitPi> slice= units.findBy(UnitPi.class, predicate, (query)-> {
			FluentQuery.FetchableFluentQuery<UnitPi> queryUse = query.as(UnitPi.class);    //类型转换要求; <R> FetchableFluentQuery<R> as(Class<R> resultType); UnitPi.class
			return  queryUse.page(pageable);
		});
		return slice;
	}
	/**不采用默认查询接口的； 需要自定义过滤参数规则，需要分页的：目前最佳方案。
	 * unitRepository目前最佳方案
	 * */
	@QueryMapping
	public <T> Slice<UnitPi> units(@Argument UnitInputProjection uinput) {
		QUnit q=QUnit.unit;
		Pageable pageable= PageRequest.of(0, 11);
		Predicate predicate=null;
		predicate = q.cancel.eq(uinput.getCancel())
				.and(q.indCod.startsWithIgnoreCase(uinput.getIndCod()));
		//Map<String, ? extends Expression<?>> mapFieldBind=null;
		//Map<String,Expression<?>>  mapFieldBind= createBindings(beanArgs.toArray(new Expression<?>[0]));
		QBeanMy<?> piExp=new QBeanMy<Unit>(Unit.class, q.id,q.indCod,q.cancel,q.area
				,q.company.id,q.company.name ,q.person.id,q.person.name);
		piExp.bindLeftJoin(q.company,q.person);
		//QBeanMy<?>  piExp=new QBeanMy<Unit>(Unit.class,q.id,q.indCod,q.cancel,q.company.id,q.company.name);
		//Slice<UnitPi> slice= unitRepository.readAllBy(pageable, UnitPi.class); //unitRepository.<UnitPi,Slice<UnitPi>>findBy();
		//List<String> properties= Lists.newArrayList("id","indCod","cancel","company.id","company.name");
		Slice<UnitPi> slice= units.findBy(piExp, predicate, (query)-> {
			FluentQuery.FetchableFluentQuery<UnitPi> queryUse = query.as(UnitPi.class);    //返回类型要求; <R> FetchableFluentQuery<R> as(Class<R> resultType); UnitPi.class
			//queryUse= queryUse.project("id","indCod","cancel"); //没影响到select！但是影响返回可用字段，所以关联字段1+N可能会被抑制掉。对父类findBy有好处，自定做findBy就没啥用了。
			return  queryUse.page(pageable);
		});
		//执行save()/delete()首先会从数据库查询最新数据的(所有实体字段)以及非懒加载实体,事务提交时会自动update set company_id=?,会包括所有实体字段的以及此次修改的关联实体。
		return slice;
	}
	@QueryMapping
	@SuppressWarnings("unchecked")
	public List<UnitPi> unitRepository_所有(@Argument UnitInputProjection uinput) {
		Pageable pageable= PageRequest.of(0, 11);
		Predicate predicate=null;
		predicate = QUnit.unit.cancel.eq(uinput.getCancel())
				.and(QUnit.unit.indCod.startsWithIgnoreCase(uinput.getIndCod()));
		//Slice<UnitPi> slice= unitRepository.readAllBy(pageable, UnitPi.class); //unitRepository.<UnitPi,Slice<UnitPi>>findBy();
		//FluentQuery.FetchableFluentQuery<UnitPi>
		Collection<String> properties= Lists.newArrayList("id","indCod","cancel");
		List<UnitPi> slice= units.findBy(UnitPi.class, predicate, (query)-> {
			//FluentQuery.FetchableFluentQuery<UnitPi> queryToUse =  query;
			//	QBean<UnitPi> prjType= Projections.bean(UnitPi.class);
			FluentQuery.FetchableFluentQuery<UnitPi> queryUse = query.as(UnitPi.class);    //<R> FetchableFluentQuery<R> as(Class<R> resultType); UnitPi.class
			//queryUse= queryUse.project(properties);   //仅是指示Hint:FetchGraph。如果做了pi path就没必要;project()约束输出的Fetch;而select字段屏蔽做不到！
			queryUse= queryUse.project("id","indCod","cancel");
			//queryUse = queryUse.sortBy(Sort.by("id").ascending());
			//	FluentQuery.FetchableFluentQuery<Unit> queryUse = query.<UnitPi>project("id","indCod","cancel");
			//原来自spring-graphql：org/springframework/graphql/data/query/QuerydslDataFetcher.java:506 实际基础用上FluentQuery的。
			//queryToUse = queryToUse.as(Unit.class);报错Class-based DTOs are not yet supported.
			return  queryUse.all();
		});
		return slice;
	}
	//最简单连EnableJpaRepositories都没加，就extends ProjectionRepository反而可以投影成功!
	@QueryMapping
	@SuppressWarnings("unchecked")
	public Slice<UnitPi> unitRepository_simple(@Argument UnitInputProjection uinput) {
		Pageable pageable= PageRequest.of(0, 11);
		Predicate predicate=null;
		predicate = QUnit.unit.cancel.eq(uinput.getCancel())
				.and(QUnit.unit.indCod.startsWithIgnoreCase(uinput.getIndCod()));
		//Slice<Unit> slice=unitRepository.readAllBy(pageable, Unit.class);
		Slice<UnitPi> slice= units.readAllBy( pageable, UnitPi.class);
		/*Slice<UnitPi> slice=unitRepository.findBy(predicate, query -> {
			FluentQuery.FetchableFluentQuery<?> queryToUse = (FluentQuery.FetchableFluentQuery<?>) query;
			queryToUse = queryToUse.sortBy(Sort.by("id").ascending());
			//正常是 queryToUse = queryToUse.project("id","indCod","cancel");
			//原来自spring-graphql：org/springframework/graphql/data/query/QuerydslDataFetcher.java:506 实际基础用上FluentQuery的。
			//queryToUse = queryToUse.as(Unit.class);报错Class-based DTOs are not yet supported.
			queryToUse = queryToUse.as(UnitPi.class);    //<R> FetchableFluentQuery<R> as(Class<R> resultType);
			return (Slice<UnitPi>) queryToUse.page(pageable);
		});*/
		return slice;
	}



	@QueryMapping
	@SuppressWarnings("unchecked")
	public Slice<Unit> unitRepository6(@Argument UnitInputProjection uinput) {
		Pageable pageable= PageRequest.of(0, 11);
		Predicate predicate=null;
		predicate = QUnit.unit.cancel.eq(uinput.getCancel())
				.and(QUnit.unit.indCod.startsWithIgnoreCase(uinput.getIndCod()));
//简单成功的	Slice<Unit> slice=unitRepository.readAllBy( pageable, Unit.class); 没有predicate的是可以运行！
		//失败！没法直接加predicate Slice<Unit>  slice= unitRepository.readAllBy(predicate, pageable, Unit.class);
		//必须上 <S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
		//Slice<Unit> slice= (Slice<Unit>) unitRepository.findAll(predicate); //报错class java.util.ArrayList cannot be cast但这里还没执行count()语句的！
		//Function<FluentQuery.FetchableFluentQuery<S>, R>
		//class java.util.ArrayList cannot be cast to class org.springframework.data.domain.Slice
/*		Slice<Unit> slice=unitRepository.findAll(new Specification<Unit>() {
			@Override
			public jakarta.persistence.criteria.Predicate toPredicate(Root<Unit> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				return null;
			}
		},pageable);*/

		Slice<Unit> slice=null;//unitRepository.findAll(predicate, pageable);
		//long sad= unitRepository.count(predicate);
/*		Slice<Unit> slice2=unitRepository.findBy(predicate, query -> {
			FluentQuery.FetchableFluentQuery<Unit> queryToUse = (FluentQuery.FetchableFluentQuery<Unit>) query;
				//queryToUse = queryToUse.sortBy(sort);
			//if (requiresProjection(resultType)){
			//queryToUse = queryToUse.as(Unit.class); //else {		//Class<R> resultType
			queryToUse = queryToUse.project("id","indCod","cancel");		//(): buildPropertyPaths(env.getSelectionSet(), resultType)
			return  queryToUse.page(pageable); //queryToUse.all();
		});*/
		return slice;
	}
	@QueryMapping
	public Connection<Unit> unitRepository2(GraphQLContext ctx, DataFetchingEnvironment dfe) throws Exception {

		Pageable pageable= PageRequest.of(0, 2);
		Sort sort=null;
		//Predicate predicate=null;
		//	 predicate = QBook.book.id.equalsIgnoreCase(bookInput.getId())
		//			.and(QBook.book.name.startsWithIgnoreCase(bookInput.getName()));
		//books.findAll(predicate, pageable); ,company:{ad:{city:{name:"福建省福州市"}}}
		DataFetcher<Iterable<Unit>> dataFetcher =
			null;//	QuerydslDataFetcher.builder(unitRepository).many();		//可加.sortBy(sort)
		SimpleListConnection<Unit> dataFetcher2 =new SimpleListConnection<>((List<Unit>) dataFetcher.get(dfe));
		return dataFetcher2.get(dfe);
		//return books.findAll(pageable);
	}
/* 可以成功的方式
{
    books(bookInput:{name:"做法是",id:"fff"}) {
        id,name,url  snapshotsEnabled
    }
}
* */


	/*
{
    books(name:"仅仅") {
          id,name,url  snapshotsEnabled
    }
}

	* */
/*	@QueryMapping
	public Page<Book> books13(GraphQLContext ctx, DataFetchingEnvironment dfe) throws Exception {

		Pageable pageable= PageRequest.of(0, 2);
		Sort sort=null;
		//Predicate predicate=null;
		//	 predicate = QBook.book.id.equalsIgnoreCase(bookInput.getId())
		//			.and(QBook.book.name.startsWithIgnoreCase(bookInput.getName()));
		//books.findAll(predicate, pageable);
		DataFetcher<Iterable<Book>> dataFetcher =
				QuerydslDataFetcher.builder(unitRepository).many();		//可加.sortBy(sort)
		SimpleListConnection<Book> dataFetcher2 =new SimpleListConnection((List) dataFetcher.get(dfe));
		return (Page<Book>) dataFetcher2.get(dfe);
		//return books.findAll(pageable);
	}*/
	@SchemaMapping(typeName="Unit", field="name" )
	public String getName(Unit unit , DataFetchingEnvironment env) {
		if(null==unit.getCompany()){
			return unit.getPerson().getName();
		}
		else  return unit.getCompany().getName();
	}
	/**某单位内不归属具体部门的管理层*/
	@SchemaMapping(field="staff")
	public List<User> staff(Unit unit, DataFetchingEnvironment env) {
		BooleanBuilder builder = new BooleanBuilder();
		QUser qm = QUser.user;
		builder.and(qm.unit.eq(unit)).and(qm.dep.isNull());		//qm.office 科室必然也=null的。
		List<User> list= (List<User>)userRepository.findAll(builder);
		return list;
	}
}



//,company:{id:"04439cb4-9e13-43f3-ae58-0371d124a8dd",name:"福建省福州市",no:"694359076"}
@ProjectedPayload
interface UnitInputProjection {
	Boolean getCancel();
	String getIndCod();

}

/*
实际 关键： org/springframework/graphql/data/query/QuerydslDataFetcher: ManyEntityFetcher 接口执行入口
		@Override
		@SuppressWarnings("unchecked")
		public Iterable<R> get(DataFetchingEnvironment env) {    #QuerydslPredicateExecutor<T> executor
			return this.executor.findBy(buildPredicate(env), query -> {
				FetchableFluentQuery<R> queryToUse = (FetchableFluentQuery<R>) query;

				if (this.sort.isSorted()){
					queryToUse = queryToUse.sortBy(this.sort);
				}

				if (requiresProjection(this.resultType)){
					queryToUse = queryToUse.as(this.resultType);
				}
				else {
					queryToUse = queryToUse.project(buildPropertyPaths(env.getSelectionSet(), this.resultType));
				}

				return queryToUse.all();
			});
		}
public Slice<Unit> unitRepository(@QuerydslPredicate Predicate predicate, @Argument UnitInputProjection uinput)
没办法注入@QuerydslPredicate Predicate predicate, 只针对Rest MVC,无法用于graphQL的端点和接口controller; Cannot invoke "Object.getClass()" because "source" is null
  select eqp0_.id as id2_19_0_, eqp0_.aid  from Eqp eqp0_
	left outer join Boiler eqp0_1_ on eqp0_.id=eqp0_1_.id
	left outer join Vessel eqp0_2_ on eqp0_.id=eqp0_2_.id
	left outer join FactoryVehicle eqp0_3_ on eqp0_.id=eqp0_3_.id left outer join Crane eqp0_4_ on eqp0_.id=eqp0_4_.id left outer join Pipeline eqp0_5_ on eqp0_.id=eqp0_5_.id
	left outer join Amusement eqp0_6_ on eqp0_.id=eqp0_6_.id left outer join Ropeway eqp0_7_ on eqp0_.id=eqp0_7_.id left outer join Elevator eqp0_8_ on eqp0_.id=eqp0_8_.id
	left outer join Isp isp1_ on eqp0_.isp1_id=isp1_.id left outer join Detail detail2_ on isp1_.bus_id=detail2_.id left outer join Eqp eqp3_ on isp1_.dev_id=eqp3_.id
	left outer join Boiler eqp3_1_ on eqp3_.id=eqp3_1_.id left outer join Vessel eqp3_2_ on eqp3_.id=eqp3_2_.id left outer join FactoryVehicle eqp3_3_ on eqp3_.id=eqp3_3_.id
	left outer join Crane eqp3_4_ on eqp3_.id=eqp3_4_.id left outer join Pipeline eqp3_5_ on eqp3_.id=eqp3_5_.id left outer join Amusement eqp3_6_ on eqp3_.id=eqp3_6_.id
	left outer join Ropeway eqp3_7_ on eqp3_.id=eqp3_7_.id left outer join Elevator eqp3_8_ on eqp3_.id=eqp3_8_.id left outer join Isp isp4_ on eqp3_.isp2_id=isp4_.id
	left outer join Report report5_ on isp4_.report_id=report5_.id left outer join ApprovalStm approvalst6_ on report5_.stm_id=approvalst6_.id
	left outer join Circulation circulatio7_ on approvalst6_.cur_id=circulatio7_.id left outer join Report reps8_ on isp4_.id=reps8_.isp_id
	where eqp0_.id=?
* */
